package logger

import (
	"fmt"
	"os"
	"sync"
	"sync/atomic"

	"gitee.com/night-tc/gobige/threads"

	"github.com/cxzgb123/toml"
)

/*
服务器上的日志系统
如果是Test运行用到日志的话,使用的是默认配置不会生成文件等逻辑
如果是正常的服务,需要在使用之前运行Init逻辑
*/

var (
	logGlobal *LoggerMgr
	one       sync.Once
	istest    bool
)

// Init 初始化日志系统。
// 参数:
//
//	cfg: 日志配置文件路径。
//	srvname: 服务名称。
//	thgo: 协程管理器实例。
func Init(cfg string, srvname string, thgo *threads.ThreadGo) {
	one.Do(func() {
		var logcfg *LogFileConfig
		if _, err := os.Stat(cfg); !os.IsNotExist(err) {
			logcfg = new(LogFileConfig)
			_, err := toml.DecodeFile(cfg, logcfg)
			if err != nil {
				fmt.Printf("Logger Init log.toml err:%s\n", err)
			}
		} else {
			fmt.Println("Logger Init log.toml not exist.")
			logcfg = defaultLogConfig
			//如果没有对应的日志配置就生成一个
			GenLogConfigFile(cfg)
		}
		logcfg.LogFileName = srvname
		logGlobal = newLoggerMgr(thgo,
			LoggerSetConfig(logcfg))
	})
}

// 是否为测试模式
func IsTest() bool {
	return istest
}

// Flush 停止日志系统，清理资源。
func Flush() {
	logGlobal.Stop()
}

// ReLoadKeys 重新加载日志Key。
// 参数:
//
//	Keys: 新的日志Key列表。
func ReLoadKeys(Keys []string) {
	logGlobal.lk.Lock()
	defer logGlobal.lk.Unlock()
	logGlobal.tmpKeyList = Keys
}

// ReLoadLevel 重新加载日志等级。
// 参数:
//
//	level: 新的日志等级。
func ReLoadLevel(level logLevel) {
	atomic.StoreInt64(&logGlobal.config.LogFileLevel, level)
}

// CheckKey 检查是否包含指定的日志Key。
// 参数:
//
//	logKey: 日志Key。
//
// 返回值:
//
//	bool: 是否包含指定Key。
func CheckKey(logKey LogKeyEnum) bool {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	return logGlobal.checkKey(logKey)
}

// Debugf 记录调试日志（格式化字符串）。
// 参数:
//
//	logKey: 日志Key。
//	format: 日志内容的格式化字符串。
//	params: 格式化参数。
func Debugf(logKey LogKeyEnum, format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelDebug {
		return
	}
	if !logGlobal.checkKey(logKey) {
		return
	}
	logGlobal.debug(logKey, fmt.Sprintf(format, params...))
}

// Infof 记录信息日志（格式化字符串）。
// 参数:
//
//	format: 日志内容的格式化字符串。
//	params: 格式化参数。
func Infof(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelInfo {
		return
	}
	logGlobal.info(fmt.Sprintf(format, params...))
}

// Warnf 记录警告日志（格式化字符串）。
// 参数:
//
//	format: 日志内容的格式化字符串。
//	params: 格式化参数。
func Warnf(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelWarn {
		return
	}
	logGlobal.warn(fmt.Sprintf(format, params...))
	// _, file, line, _ := runtime.Caller(1)
	// logGlobal.warn(fmt.Sprint(format, "\n", file, ":", line), params...)
}

// Errorf 记录错误日志（格式化字符串）。
// 参数:
//
//	format: 日志内容的格式化字符串。
//	params: 格式化参数。
func Errorf(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelError {
		return
	}
	logGlobal.error(fmt.Sprintf(format, params...))
}

// Fatalf 记录致命错误日志（格式化字符串）。
// 参数:
//
//	format: 日志内容的格式化字符串。
//	params: 格式化参数。
func Fatalf(format string, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelFatal {
		return
	}
	logGlobal.fatal(fmt.Sprintf(format, params...))
}

// Debug 记录调试日志。
// 参数:
//
//	logKey: 日志Key。
//	params: 日志内容。
func Debug(logKey LogKeyEnum, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelDebug {
		return
	}
	if !logGlobal.checkKey(logKey) {
		return
	}
	logGlobal.debug(logKey, fmt.Sprintf(getFormat(len(params)), params...))
}

// 调试等级上线后不需要看到的日志,调试用,可以使用Key来临时开关的日志(这个会受GM 进行筛选)
func ScreenDebug(logKey LogKeyEnum, params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelDebug {
		return
	}
	logGlobal.debug(logKey, fmt.Sprintf(getFormat(len(params)), params...))
}

// Info 记录信息日志。
// 参数:
//
//	params: 日志内容。
func Info(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelInfo {
		return
	}
	logGlobal.info(fmt.Sprintf(getFormat(len(params)), params...))
}

// Warn 记录警告日志。
// 参数:
//
//	params: 日志内容。
func Warn(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelWarn {
		return
	}
	logGlobal.warn(fmt.Sprintf(getFormat(len(params)), params...))
	// _, file, line, _ := runtime.Caller(1)
	// logGlobal.warn(fmt.Sprint(getFormat(len(params)), "\n", file, ":", line), params...)

}

// 警告等级一般是配置表有错,但不影响正常运行等
func MysqlWarn(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelWarn {
		return
	}
	logGlobal.warn(fmt.Sprintf(getFormat(len(params)), params...))
}

// Error 记录错误日志。
// 参数:
//
//	params: 日志内容。
func Error(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelError {
		return
	}
	logGlobal.error(fmt.Sprintf(getFormat(len(params)), params...))
}

// Fatal 记录致命错误日志。
// 参数:
//
//	params: 日志内容。
func Fatal(params ...interface{}) {
	one.Do(func() { logGlobal = newLoggerMgr(nil) })
	if logGlobal.config.GetAtomicFileLevel() < LogLevelFatal {
		return
	}
	logGlobal.fatal(fmt.Sprintf(getFormat(len(params)), params...))
}

const (
	LOGFILE_INIT_NUMBER int = 0
)
